#include "frmmain.h"
#include "device_info.h"
#include <algorithm>

frmMain::frmMain(QWidget *parent, Qt::WFlags flags)
<<<<<<< .mine
	: QMainWindow(parent, flags),fnt("Arial",14)
=======
        : QMainWindow(parent, flags),fnt("Times",14), u64MAC(0)
>>>>>>> .r35
{	
	
	ui.setupUi(this);
	ui.pic->installEventFilter(this);
	IconSize = 128;
	Interval = 40;
	Voltage = 220;
	Frequency = 50;
	Power = 0;
	SelectedDevice = -1;

	LoadDeviceList();

	UpdateInfo();

	timer.setInterval(500);
	connect(&timer,SIGNAL(timeout()),this,SLOT(timerEvent()));
	timer.start();

#ifdef _WIN32
	port = new QextSerialPort("COM70");
#else
        port = new QextSerialPort("/dev/ttyUSB0");
#endif
        port->setBaudRate(BAUD115200);
	port->setQueryMode(QextSerialPort::EventDriven);
       
        //Let's parser doing all work with ATJenie
    


	/*Parser = new ATJenie_Parser(*port);
        connect(Parser, SIGNAL(NetworkJoined(AtJenie_NTU)),
                this, SLOT(NetworkConnected(AtJenie_NTU)));
        connect(Parser, SIGNAL(RegisterServiceResponse()),
                this, SLOT(RegisterServiceResponse()));
        connect(Parser, SIGNAL(ServiceRequestResponse(uint64_t,uint32_t)),
                this, SLOT(ServiceRequestResponse(uint64_t,uint32_t)));
	if (Parser->SendReset())
		qDebug("Reset success");
        if (Parser->ConfigureATJenie())
		qDebug("Cmd success");
<<<<<<< .mine
        Parser->CreateNetwork(0x1234, 15, 0x0, false, true);*/
=======
        //if (Parser->CreateNetwork(0x2012, 12, 0x7, false, true))
        if (Parser->JoinNetwork(ATJenie_DeviceType_Router, 0x1234, 12, 0x3, false, true))
                qDebug("Network created successful");
        if (!Parser->WaitForNetwork())
            throw QString(tr("Network wasn't created in time."));
        if (Parser->RegisterServices(0x7))
                qDebug("Network created successful");
>>>>>>> .r35

        tsPowerServiceCmd_ ps = { 0 };
        ps.u8CmdCode = PWRSVC_CMD_ON;
        ps.u8ChMask = PWR_CH_LOG_ALL;

        if (!Parser->SendListOfRequestedServices(0x2, ATJenie_TypeOfMatch_Any))
            throw;
        while(!u64MAC)
            qApp->processEvents();
        if (!Parser->Bind(0x1, u64MAC, 0x2))
            throw;
        QByteArray Data;
        Data.resize(Data.size() + sizeof(ps.u8ChMask) + sizeof(ps.u8CmdCode));
        //memcpy(&(ps.u8CmdCode), Data.data(), sizeof(ps.u8CmdCode));
        //memcpy(&(ps.u8ChMask), Data.data(), sizeof(ps.u8ChMask));
        Data[0] = ps.u8CmdCode;
        Data[1] = ps.u8ChMask;
        Parser->SendDataToService(1, Data);
}

frmMain::~frmMain()
{
	//port->close();
	delete port;
	qApp->quit();
}

void frmMain::ConnectDevice(int dev_id)
{
	devices[dev_id].m_is_connected = true;
	this->ui.pic->update();
}

void frmMain::DisconnectDevice(int dev_id)
{
	devices[dev_id].m_is_connected = false;
	this->ui.pic->update();
}

void frmMain::LoadDeviceList()
{
	QSettings settings("devices.ini", QSettings::IniFormat);
	settings.setPath(QSettings::IniFormat, QSettings::UserScope, QDir::currentPath());
	int size = settings.beginReadArray("Devices");
	for (int i = 0; i < size; ++i)
	{
		settings.setArrayIndex(i);
		if(!settings.contains("Name") || !settings.contains("Img"))
			break;
		devices.push_back(TDevice(settings.value("Name").toString()));
		devices[i].Icon = QImage(settings.value("Img").toString());
		devices[i].Power = settings.value("Power").toFloat();
		devices[i].Accuracy = settings.value("Accuracy").toFloat();
		devices[i].m_is_connected = false;
	}
	settings.endArray();
}

void frmMain::UpdateInfo()
{
	QString info =  "Voltage: "+QString::number(Voltage)+"V\n"+
		"Frequency: "+QString::number(Frequency)+"Hz\n"+
		"Total power consumption: "+QString::number(Power)+"kW";
	ui.lblGeneralParams->setText(info);
}

void frmMain::pic_Paint()
{
	int x = Interval,y = Interval;
	
	QPainter p(ui.pic);

	p.setBrush(Qt::white);
	p.drawRect(0,0,ui.pic->width()-1,ui.pic->height()-1);

	p.setFont(fnt);
	p.setBrush(Qt::NoBrush);
	for (int i=0;i<devices.count();i++)
	{
		if (i == SelectedDevice)
			p.setPen(QPen(Qt::black,3));
		else
			p.setPen(Qt::NoPen);

		if (!devices[i].m_is_connected)
		{
			QImage image = devices[i].Icon;
			QRgb col;
			int gray;
			int width = image.width();
			int height = image.height();
			for (int j = 0; j < width; ++j)
			{
				for (int k = 0; k < height; ++k)
				{
					col = image.pixel(j, k);
					gray = qGray(col);
					if(gray==0)
						image.setPixel(j, k, col);
					else
						image.setPixel(j, k, qRgb(gray, gray, gray));
				}
			}
			p.drawImage(devices[i].Bounds, image);
		}
		else
		{
			p.drawImage(devices[i].Bounds, devices[i].Icon);
		}

		p.drawRect(devices[i].Bounds);
		p.setPen(Qt::black);
		if (devices[i].m_is_connected)
			p.drawText(QRect(devices[i].Bounds.x(),devices[i].Bounds.bottom()+3,devices[i].Bounds.width(),20),Qt::AlignCenter | Qt::AlignVCenter,
				trUtf8()+QString::number(devices[i].Power));
	}
	//p.drawText(10,10,stInfo);
}

void frmMain::pic_Resize()
{
	int x = Interval,y = Interval;

	for (QList<TDevice>::iterator it = devices.begin();it != devices.end();++it)
	{
		if (x+IconSize+Interval > ui.pic->width())
			y+=IconSize+Interval;
		(*it).Bounds = QRect(x,y,IconSize,IconSize);
		x+=IconSize+Interval;
	}
}

void frmMain::pic_ShowMenu(const QPoint& pos)
{
	if(SelectedDevice<0 || SelectedDevice>=devices.count())
		return;

    QPoint globalPos = ui.pic->mapToGlobal(pos);

    QMenu dev_menu;
	QAction actStartStop(devices.at(SelectedDevice).m_is_connected ? tr("Stop") : tr("Start"), &dev_menu);
	QAction actInfo(tr("Info"), &dev_menu);

	dev_menu.addAction(&actStartStop);
	dev_menu.addAction(&actInfo);

    QAction* selectedItem = dev_menu.exec(globalPos);
    if (selectedItem)
    {
		if(selectedItem == &actInfo)
		{
			ShowDeviceInfo(SelectedDevice);
		}
		if(selectedItem == &actStartStop)
		{
			if (devices[SelectedDevice].m_is_connected)
				DisconnectDevice(SelectedDevice);
			else
				ConnectDevice(SelectedDevice);
		}
    }
}

void frmMain::ProcessPowerConsumption(float NewPower)
{
	if (qAbs(Power-NewPower) <= 2)
	{		
		// Analyse individual power consumption
		for (int i=0;i<(int)qPow(2,devices.count());i++)
		{
			float MinBorder = 0,MaxBorder = 0;
			for (int j=0;j<devices.count();j++)
			{
				if (i & (1 << j))
				{
					MinBorder+=devices[j].Power-devices[j].Accuracy;
					MaxBorder+=devices[j].Power+devices[j].Accuracy;
				}
			}
			if (NewPower >= MinBorder && NewPower <= MaxBorder)
			{
				for (int j=0;j<devices.count();j++)
					if (i & (1 << j))
						devices[j].m_is_connected = true;
					else
						devices[j].m_is_connected = false;
				break;
			}
		}
		qSort(devices.begin(),devices.end(),DeviceCompareFunc);
		ui.pic->update();
	}
	Power = NewPower;
	UpdateInfo();
}

void frmMain::ShowDeviceInfo(int dev_id)
{
	if(dev_id<0 || dev_id>devices.count())
		return;

	device_info* dev = devices[dev_id].m_wnd;
	if(!dev)
	{
		dev = new device_info(devices[dev_id]/*, this*/);
		dev->setAttribute(Qt::WA_DeleteOnClose, true);
		dev->setWindowTitle(devices[dev_id].Name);
		devices[dev_id].m_wnd = dev;
	}
	dev->show();
	dev->activateWindow();
}

bool frmMain::eventFilter(QObject *obj, QEvent *ev)
{
	QMouseEvent *me;
	QWidget *childWidget;
	if (obj == ui.pic)
	{
		switch(ev->type())
		{
			case QEvent::Paint:
				pic_Paint();
				return true;
			case QEvent::Resize:
				pic_Resize();
				return true;
			case QEvent::MouseButtonPress:
				me = (QMouseEvent*)ev;
				SelectedDevice = -1;
				for (int i = 0;i < devices.count();i++)
					if (devices[i].Bounds.contains(me->x(),me->y()))
					{
						SelectedDevice = i;
						break;
					}
				ui.pic->update();

				if(SelectedDevice>=0 && me->button() == Qt::RightButton)
					pic_ShowMenu(me->pos());

				return true;
			case QEvent::MouseButtonDblClick:
				me = (QMouseEvent*)ev;
				for (int i = 0;i < devices.count();i++)
					if (devices[i].Bounds.contains(me->x(),me->y()))
					{
						SelectedDevice = i;
						ShowDeviceInfo(SelectedDevice);
						//QMessageBox::information(this,"Event",QString("Dbl pressed on %1").arg(i));
						break;
					}
				//childWidget = new

				return true;
		}
	}
	return false;
}

void frmMain::IdentifyDevices()
{
	//devices.sort();
}

//void frmMain::NewNode(quint64 Address,quint32 Service)
//{

//}

//void frmMain::NewData(quint64 Address, QByteArray Data)
//{
//	if (Address == MeterAddress)
//	{


//	}
//	else
//		if (Address == SocketAddress)
//		{

//		}
//}

void frmMain::timerEvent()
{
	static float prevValue = 0;
	prevValue+=2;
	ProcessPowerConsumption(prevValue);
}

void frmMain::NetworkConnected(AtJenie_NTU NTU)
{
    qDebug("Recieved NRU signal with:\n1->%u\n2->%u\n3->%u\n\n4->%u\n5->%u\n",
           NTU.u32PANID, NTU.u64AddressNode, NTU.u64AddressParent, NTU.u8Channel, NTU.u8Depth);
}

void frmMain::RegisterServiceResponse()
{
    qDebug() << "New service registered!" << endl;
}

void frmMain::ServiceRequestResponse(uint64_t u64AddressRemote, uint32_t u32ServiceMask)
{
    u64MAC = u64AddressRemote;
    qDebug("Found %u requested services with mask %u.\n", u64AddressRemote,
           u32ServiceMask);
}
